import { common_scale } from "..";
import { Bullet } from "../objects/Bullet";
import { Enemy } from "../objects/Enemy";
import { Obstacle } from "../objects/Obstacle";
import { Player } from "../objects/Player";

export class GameScene extends Phaser.Scene {
    private map: Phaser.Tilemaps.Tilemap;
    private tileset: Phaser.Tilemaps.Tileset;

    private layer: Phaser.Tilemaps.TilemapLayer;
    
    private player: Player;

    private enemies: Phaser.GameObjects.Group;
    private obstacles: Phaser.GameObjects.Group;

    private playerSafeAreas: Phaser.Types.Physics.Arcade.SpriteWithDynamicBody;
    
    private target: Phaser.Math.Vector2;
    
    constructor() {
        super({ key: 'GameScene' });
    }
    
    
    create(): void {
        this.map = this.make.tilemap({ key: 'levelMap' });
        this.tileset = this.map.addTilesetImage('tiles');
        this.layer = this.map.createLayer('tileLayer', this.tileset, 0, 0)
            .setCollisionByProperty({ collide: true })
        ;

        this.obstacles = this.add.group({
            runChildUpdate: true
        });

        this.enemies = this.add.group({});
        this.createLayerObjects();
        
        this.playerSafeAreas = this.physics.add.sprite(0, 0, 'blank')
            .setOrigin(0, 0);
        this.playerSafeAreas.setDisplaySize(800, 480)
            .setImmovable(true)
            ;
        
        // collider
        // this.player.setCollideWorldBounds(true, this.map.widthInPixels, this.map.heightInPixels, true);
        this.physics.add.collider(this.player, this.layer);
        this.physics.add.collider(this.player, this.obstacles);
        
        // bullet hit and collider
        /*this.physics.add.collider(
            this.player.getBullets(), 
            this.layer,
            this.bulletHitLayer,
            null,
            this
        ); */
        this.physics.add.collider(
            this.player.getBullets(), 
            this.obstacles,
            this.bulletHitObstacles,
            null,
            this
        );

        // enemy hit and collider
        this.enemies.getChildren().forEach( (enemy: Enemy) => {
            this.physics.add.overlap(
                this.player.getBullets(), 
                enemy,
                this.playerBulletHitEnemy,
                null,
                this
            );
            this.physics.add.overlap(
                enemy.getBullets(), 
                this.player,
                this.enemyBulletHitPlayer,
                null
            );

            this.physics.add.collider(
                enemy.getBullets(), 
                this.obstacles,
                this.bulletHitObstacles,
                null
            );

            this.physics.add.collider(
                enemy.getBullets(), 
                this.playerSafeAreas,
                this.bulletHitLayer
            );
            
            /* this.physics.add.collider(
                enemy.getBullets(), 
                this.layer,
                this.bulletHitLayer,
                null
            ); */
        }, this);

        this.cameras.main.setBounds(0, 0, this.map.widthInPixels, this.map.heightInPixels);
        this.cameras.main.setZoom( common_scale );
        this.cameras.main.startFollow(this.player);
    }


    update(): void {
        if(!this.player.active){
            return;
        }
        
        this.player.update();
        
        this.layerBoundsCheckWithPlayer(this.player);
        
        this.clearBullets(this.player.getBullets());
        

        this.enemies.getChildren().forEach( (enemy: Enemy) => {
            enemy.update();
            if(this.player.active && enemy.active){
                var angle = Phaser.Math.Angle.Between(
                    enemy.body.x,
                    enemy.body.y,
                    this.player.body.x,
                    this.player.body.y
                );
                
                enemy.getBarrel().angle = (angle + Math.PI/2) * Phaser.Math.RAD_TO_DEG;
            }
            this.clearBullets(enemy.getBullets());

            if(!enemy.active){
                console.log('enemy is dead');
                this.enemies.remove(enemy);
            }
        }, this);
    }


    private createLayerObjects(): void {
        const objects = this.map.getObjectLayer('objects').objects as any[];
        
        objects.forEach(object => {
            if( object.type === 'player' ){
                this.player = new Player({
                    scene: this,
                    x: object.x, 
                    y: object.y,
                    texture: 'tankBlue'
                });
            } else if( object.type === 'enemy' ){
                let enemy = new Enemy({
                    scene: this,
                    x: object.x, 
                    y: object.y,
                    texture: 'tankRed'
                });

                this.enemies.add(enemy);
            } else {
                let obstacle  = new Obstacle({
                    scene: this,
                    x: object.x, 
                    y: object.y,
                    texture: object.type
                });

                this.obstacles.add(obstacle);
            }
        })
    }
    
    private bulletHitLayer(bullet: Bullet) {
        bullet.destroy();
    }
    

    private bulletHitObstacles(bullet: Bullet, obstacle: Obstacle) {
        bullet.destroy();
    }

    private enemyBulletHitPlayer(bullet: Bullet, player: Player) {
        bullet.destroy();
        player.updateHealth();
    }

    private playerBulletHitEnemy(bullet: Bullet, enemy: Enemy) {
        bullet.destroy();
        enemy.updateHealth();
    }


    clearBullets(group: Phaser.GameObjects.Group): void {
        group.getChildren().forEach( (bullet: Bullet) => {
            if(!bullet.active){
                // console.log('enemy bullet destoryed');
                group.remove(bullet);
                return;
            }
            
            if(bullet.x < 0 || bullet.x > this.map.widthInPixels
                || bullet.y < 0 || bullet.y > this.map.heightInPixels
            ){
                // console.log('bullet desctoryed and remove x, y', bullet.x, bullet.y);
                bullet.destroy();
                group.remove(bullet);
            }
        })
    }
        
    layerBoundsCheckWithPlayer(entity: Phaser.GameObjects.Image){
        if(entity.x < entity.width/2){
            entity.x = entity.width/2;
        }

        if(entity.x > (this.map.widthInPixels - entity.width/2)){
            entity.x = (this.map.widthInPixels - entity.width/2);
        }

        if(entity.y < entity.height/2){
            entity.y = entity.height/2
        }

        if(entity.y > (this.map.heightInPixels - entity.height/2-16)){
            entity.y = (this.map.heightInPixels - entity.height/2-16)
        }
    }
}